﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;
using NSsh.Common.Utility;
using NSsh.Server.Configuration;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using NUnit.Framework.SyntaxHelpers;
using NSsh.Common;
using System.Threading;

namespace NSsh.Server.Tests
{
    [CoverageExclude("Too hard to test at the moment.")]
    [Ignore("Tests fail sometimes.")]
    [TestFixture]
    public class NSshServiceFixture
    {
        IPEndPoint endpoint1 = new IPEndPoint(IPAddress.Loopback, 22122);
        IPEndPoint endpoint2 = new IPEndPoint(IPAddress.Loopback, 22123);
        
        NSshService _service;
        NSshServiceConfiguration _configuration;
        ISshSession _session;
        MockRepository _mockRepository;

        [SetUp]
        public void Setup()
        {
            _mockRepository = new MockRepository();
            _session = _mockRepository.CreateMock<ISshSession>();
            _configuration = new NSshServiceConfiguration();

            Dependency.Clear();
            Dependency.RegisterInstance<NSshServiceConfiguration>("NSshServiceConfiguration", _configuration);
            Dependency.RegisterInstance<ISshSession>("ISession", _session);
        }

        public void StartAndStopService(MethodInvoker runningAction)
        {
            _configuration.ListenEndPoints.Add(endpoint1);
            _configuration.ListenEndPoints.Add(endpoint2);

            _service = new NSshService();
            _service.Start();
            Thread.Sleep(500);

            Assert.That(_configuration.ListenEndPoints,
                Is.SubsetOf(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()));

            if (runningAction != null)
            {
                runningAction();
            }

            _service.Stop();
            Thread.Sleep(500);

            foreach (IPEndPoint endPoint in _configuration.ListenEndPoints)
            {
                Assert.That(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(),
                    Has.No.Member(endPoint));
            }
        }

        [Test]
        public void ShouldListenOnPorts()
        {
            StartAndStopService(null);
        }

        [Test]
        public void ShouldAcceptConnection()
        {
            using (_mockRepository.Record())
            {
                _session.SocketStream = null;
                LastCall.On(_session).IgnoreArguments();

                _session.Process();
                LastCall.On(_session).Do(new MethodInvoker(delegate
                    {
                        _service.DeregisterSession(_session);
                    }));
            }

            using (_mockRepository.Playback())
            {
                StartAndStopService(new MethodInvoker(delegate
                    {
                        TcpClient client = new TcpClient();
                        client.Connect(endpoint1);
                        client.Close();
                    }));
            }
        }
    }
}
